/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 - 2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/

package com.genia.toolbox.web.taglib.js;

import java.io.IOException;
import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.tagext.TagSupport;

import org.springframework.context.i18n.LocaleContextHolder;

import com.genia.toolbox.web.constant.SpringBeanNames;
import com.genia.toolbox.web.taglib.head.js.JsScriptContainer;

/**
 * taglib to display a date with a format on a timezone.
 */
@SuppressWarnings("serial")
public class SpringDisplayDateTag
    extends TagSupport
{

  /**
   * File name containing function.
   */
  private static final String JS_FILE_NAME = "/integration/com/genia/toolbox/web/taglib/js/displayDateToolboxWeb.js";

  /**
   * date property.
   */
  private Date date;

  /**
   * format to apply on date.
   */
  private String format;

  /**
   * timezone to work on.
   */
  private String timeZone;

  /**
   * the {@link JsScriptContainer} to use.
   */
  private JsScriptContainer jsScriptContainer;



  /**
   * Processing of the end tag.
   * 
   * @return EVAL_PAGE
   * @throws JspException
   *           if any
   */
  @Override
  public int doStartTag()
      throws JspException
  {
    try {
      if (getTimeZone() == null) {
        pageContext.getOut().write(getScript());
        pageContext.getOut().write(getNoScript());
      }
      else {
        pageContext.getOut().write(getDateFormatted());
      }
    }
    catch (IOException e) {
      throw new JspException(e.getMessage());
    }

    return EVAL_PAGE;

  }



  /**
   * construct javascript to obtain a date from client timezone.
   * 
   * @return string representing javascript
   */
  private String getScript()
  {
    final StringBuilder sb = new StringBuilder();

    // Call function com_genia_toolbox_web_taglib_js_dateFormatToolboxWeb
    // located in JS_FILE_NAME
    // with date given in param, format to display and

    final DateFormatSymbols dfs = new DateFormatSymbols(LocaleContextHolder.getLocale());

    getJsScriptContainer().addScript(JS_FILE_NAME, SpringBeanNames.DEFAULT_URL_MANAGER_NAME, true, 0);
    sb.append("<script type=\"text/javascript\">").append("document.write(com_genia_toolbox_web_taglib_js_dateFormatToolboxWeb(new Date(" + getDate().getTime() + "),'" + getFormat() + "',").append(
        "[");
    for (String shortDayName : dfs.getShortWeekdays()) {
      if (shortDayName.trim().length() != 0) {
        sb.append("'" + shortDayName + "',");
      }
    }
    for (String dayName : dfs.getWeekdays()) {
      if (dayName.trim().length() != 0) {
        sb.append("'" + dayName + "',");
      }
    }
    sb.append("],[");
    for (String shortMonthName : dfs.getShortMonths()) {
      if (shortMonthName.trim().length() != 0) {
        sb.append("'" + shortMonthName + "',");
      }
    }
    for (String monthName : dfs.getMonths()) {
      if (monthName.trim().length() != 0) {
        sb.append("'" + monthName + "',");
      }
    }
    sb.append("]));").append("</script>");

    return sb.toString();
  }



  /**
   * get <noscript> markup containing a date formatted in java.
   * 
   * @return <noscript> markup containing a date formatted.
   */
  private String getNoScript()
  {
    final StringBuilder sb = new StringBuilder();

    sb.append("<noscript>").append(getDateFormatted()).append("</noscript>");
    return sb.toString();
  }



  /**
   * get a date formatted in java.
   * 
   * @return <noscript> markup containing a date formatted.
   */
  private String getDateFormatted()
  {
    final SimpleDateFormat sdf = new SimpleDateFormat(getFormat(), LocaleContextHolder.getLocale());
    final Calendar c = getTimeZone() == null ? Calendar.getInstance(TimeZone.getTimeZone("GMT"), LocaleContextHolder.getLocale()) : Calendar
        .getInstance(getTimeZone(), LocaleContextHolder.getLocale());
    sdf.setCalendar(c);

    return sdf.format(date);
  }



  /**
   * getter for the date property.
   * 
   * @return the date
   */
  public Date getDate()
  {
    return date;
  }



  /**
   * setter for the date property.
   * 
   * @param date
   *          the date to set
   */
  public void setDate(Date date)
  {
    this.date = date;
  }



  /**
   * getter for the format property.
   * 
   * @return the format
   */
  public String getFormat()
  {
    return format;
  }



  /**
   * setter for the format property.
   * 
   * @param format
   *          the format to set
   */
  public void setFormat(String format)
  {
    this.format = format;
  }



  /**
   * getter for the timeZone property.
   * 
   * @return the timeZone
   */
  public TimeZone getTimeZone()
  {
    return timeZone == null ? null : TimeZone.getTimeZone(timeZone);
  }



  /**
   * setter for the timeZone property.
   * 
   * @param timeZone
   *          the timeZone to set
   */
  public void setTimeZone(String timeZone)
  {
    this.timeZone = timeZone;
  }



  /**
   * getter for the jsScriptContainer property.
   * 
   * @return the jsScriptContainer
   */
  public JsScriptContainer getJsScriptContainer()
  {
    return jsScriptContainer;
  }



  /**
   * setter for the jsScriptContainer property.
   * 
   * @param jsScriptContainer
   *          the jsScriptContainer to set
   */
  public void setJsScriptContainer(JsScriptContainer jsScriptContainer)
  {
    this.jsScriptContainer = jsScriptContainer;
  }

}